package com.ke.rule.base;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.Ordered;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.stereotype.Component;

@Component
public class SpringContextUtils implements ApplicationContextAware {

  private static ApplicationContext ctx;

  private static class ApplicationContextSetter {
    static void setContext(final ApplicationContext ctx) {
      SpringContextUtils.ctx = ctx;
    }
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    ApplicationContextSetter.setContext(applicationContext);
  }

  public static ApplicationContext getApplicationContext() {
    return ctx;
  }

  @SuppressWarnings("unchecked")
  public static <T> T getBean(String name) throws BeansException {
    return (T) ctx.getBean(name);
  }

  public static <T> T getBean(Class<T> clazz) {
    return ctx.getBean(clazz);
  }
  
  public static <T> Map<String, T> getBeans(Class<T> clazz) throws BeansException {
    return ctx.getBeansOfType(clazz);
  }

  /**
   * 获取某类型的 bean 的集合，如果该类实现了{@link Ordered}，则按照order排序，否则按照 beanName 自然排序
   *
   * @param clazz 被匹配的类或接口
   */
  public static <T> List<T> getOrderBeansOfType(Class<T> clazz) {
    Map<String, T> map = ctx.getBeansOfType(clazz);
    if (Ordered.class.isAssignableFrom(clazz)) {
      return map.values().stream()
          .sorted(Comparator.comparingInt(e -> ((Ordered) e).getOrder()))
          .collect(Collectors.toList());
    }

    return map.entrySet().stream()
        .sorted(Map.Entry.comparingByKey())
        .map(Map.Entry::getValue)
        .collect(Collectors.toList());
  }
}
